# -*- coding: utf-8  -*-
"""
@ Autor: [[Usuário:Danilo.mac]]
@ Licença de software: GNU General Public License (GPL) e Creative Commons Attribution/Share-Alike (CC-BY-SA)

Utilize os seguntes comandos:

-avaliar:PÁGINA         Mostra uma avaliação com base nos parâmeros pré-estabelecidos.

-avaliar                Faz com que todas as qualidades sejam avaliadas.
                        Note que -avaliar e -avaliar: são dois comandos diferentes

-adicionar:TEMA         Adiciona esse tema à marca se ele já não existir. Para mais de um
                        tema use a barra vertical: TEMA1|TEMA2

-exceção:TEMA           Só adiciona o tema se TEMA não estiver na marca.

-imp:TEMA:I             Adiciona importância I para TEMA. Para mais de um tema separe
                        com ";", exemplo: -imp:TEMA1:2;TEMA2:3

-eimp:I                 Só adiciona a importância se a importância já não for I. Para mais
                        exceções separe com vírgula, exemplo: -eimp:3,4

-simular                Não salva a edição, apenas mostra o diff na tela.

-- Comandos para especificar as páginas que serão trabalhadas --

Este script utiliza a classe GeneratorFactory para especificar as páginas, veja a documentação
com a lista completa dos comandos no arquivo pagegenerators.py ou utilize o comando abaixo:

-comandos               Exibe na tela todos os comandos disponíveis para especificar as páginas
"""
import re, time
import wikipedia as pywikibot
import catlib, pagegenerators
from datetime import date


problemas = [u'artigo com problemas', u'artigo longo', u'artigo sobre direito com problemas', u'bsre', u'coi', u'caracteres não-padrão',
 u'conflito interwiki', u'contextualizar2', u'conteúdo parcial', u'controverso', u'corrigir', u'ctx2', u'curiosidades', u'direitos-autorais',
 u'disputa-bpv', u'divisão', u'em tradução', u'expandir', u'expandir2', u'fusão', u'fusão com', u'fusão de', u'fusão vot', u'global',
 u'global/brasil', u'global/lusofonia', u'global/portugal', u'hanzi', u'idioma estrangeiro', u'matrad', u'mtag', u'multitag', u'má introdução',
 u'má tradução', u'não informado', u'não informado n', u'não-enc', u'não-enciclopédico', u'não-enciclopédico2', u'parcial', u'parcialcontroverso',
 u'publicidade', u'rec', u'reciclagem', u'reciclar-sobre', u'ren-pag', u'renomear página', u'revisão', u'revisão de tradução', u'revisão-sobre',
 u's-fontes-bpv', u'sem cat', u'sem-fontes-bpv', u'sem-fontes-sobre', u'semimagem-arquitetura', u'semimagem-sobre', u'separar', u'suspeito2',
 u'tradução de', u'vda2', u'wikificação']
bpd = re.compile(ur'(?<={{).+?(?=\||\n|}})') # busca predefinições
bp = re.compile(ur'(?:^|\n\n|==\n)[^*\n].{100,}?(?=\n\n|\n==)') # busca parágrafos
br = re.compile(ur'{{[Rr]efer[eê]ncias|{{[Rr]ef-?section|{{[Rr]odapé referências|==.*?[Rr]eferências.*?==|{{[Rr]eflist') # busca seção de referências
bl = re.compile(ur'\[\[[^:]*?\]\]') # busca ligações internas
bs = re.compile(ur'(?s)\n== ?([^=\n}{]+?) ?==(.+?)(?=\n==[^=\n]|$)') # busca seções
bss = re.compile(ur'\n===[^=\n]+?===\n') # busca subseções
bref = re.compile(ur'<ref[^\n/]*?>.*?</ref>|<ref .+?/>',re.I|re.S) # busca notas de rodapé/referências
brefname = re.compile(ur'(?<=<ref name=).+?(?= />|/>| >|>)',re.I)
bi = re.compile(ur'\[\[(ficheiro|imagem?|file|arquivo):.*?(\||\]\])|{{imagem dupla\||\| ?imagem *=.*?\.[a-z]{3,4}',re.I) # busca imagens
excecoes = [u'Referências',u'Ver também',u'Notas',u'Notas e referências',u'Discografia',u'Galeria de imagens',
	u'Referências gerais',u'Leitura adicional',u'Subdivisões',u'Leitura recomendada',u'Ligações externas',u'Bibliografia'] #exeções para seções
	
def avaliar(page):
    try: texto = page.get()
    except pywikibot.IsRedirectPage: texto = page.getRedirectTarget().get()
    if len(texto) < 2000: return (1,u'menos de 2000 bytes')
    predefs = dict([(p.lower(),p) for p in bpd.findall(texto)])
    if u'artigo destacado' in predefs: return (6,u'artigo destacado')
    if u'artigo bom' in predefs: return (5,u'artigo bom')
    ref = br.search(texto)
    if not ref and len(texto) < 8000: return (1,u'menos de 8000 bytes e não tem referências')
    paragrafos = bp.findall(bref.sub('',texto))
    wkf = [x for x in paragrafos if len(x) > 2504]
    if wkf: return (1,u'parágrafo muito grande (%d bytes): "%s..."' % (len(wkf[0]),wkf[0][0:23]))
    wikilinks = bl.findall(texto)
    if len(wikilinks) < 10: return (1,u'menos de 10 ligações internas')
    subp = filter(lambda x:x.find(u'. ') == -1,paragrafos)
    if len(paragrafos) - (len(subp)/2) < 5: return (1,u'menos de 5 parágrafos')
    
    # Verificando parâmetros para qualidade 3:
    secoes = bs.findall(texto)
    subsec = bss.findall(texto)
    #if len(secoes) + (len(subsec)/5) < 2: return (1,u'menos de 2 seções')
    for predef in [u'mínimo',u'contexto',u'reciclagem',u'reciclar-sobre']:
	if predef in predefs: return (1,u'encontrado [[predefinição:%s]]' % predefs[predef])
    if not ref: return (2,u'não tem seção de referências')
    if len(texto) < 12000: return (2,u'menos de 12000 bytes')
    if len(wikilinks) < 30: return (2,u'menos de 30 ligações internas')
    if len(secoes) + (len(subsec)/5) < 2: return (2,u'menos de 2 seções')
    refs = bref.findall(texto)
    refnames = brefname.findall(texto)
    nrefs = len(refs) - len(refnames) + len(set(refnames))
    if nrefs < 5: return (2,u'menos de 5 referências')
    imagens = bi.findall(texto)
    if len(imagens) < 1: return (2,u'não tem imagem')
    for predef in [u'esboço',u'wikificação',u'revisão',u'revisão-sobre']:
	if predef in predefs: return (2,u'encontrado [[predefinição:%s]]' % predefs[predef])
    
    # Verificando parâmetros para qualidade 4:
    if len(texto) < 20000: return (3,u'menos de 20000 bytes')
    if len(wikilinks) < 50: return (3,u'menos de 50 ligações internas')
    if len(secoes) + (len(subsec)/5) < 4: return (3,u'menos de 4 seções')
    if nrefs < 10: return (3,u'menos de 10 referências')
    if len(imagens) < 2: return (3,u'só tem uma imagem')
    for predef in problemas:
	if predef in predefs: return (3,u'encontrado [[predefinição:%s]]' % predefs[predef])
    for s in secoes:
	if s[0] not in excecoes:
	    if not bref.search(s[1]) and len(bp.findall(s[1])) > 1:  return (3,u'não foram encontradas referências na seção "%s"' % s[0])
    
    # Nada encontrado:
    return (4,u'indique para [[WP:EAD|EAD]] quando o artigo satisfizer os [[Wikipédia:O que é um artigo bom?|critérios de artigo bom]]')

bmarca = re.compile(u'{{[Mm]arca de projeto\|?([^\n}]*?)}}') #busca a marca
bmarcas = re.compile(u'{{(?:Predefinição:)?([Cc]lassificação/)?(([Áá]lbuns)|[^\n\|}]+?)(?(1)[|}]|(?(3)[|}]|/[Mm]arca))\|?([^\n}]*?)}}?\n?') # busca marcas antigas
bqua = re.compile(u'qualidade ?= ?0?(\d|A[BD])')
bimp = re.compile(u'importância ?= ?0?(\d)')
brev = re.compile(u'rev ?= ?\d{8}')
qs = [u'1',u'2',u'3',u'4',u'5',u'AB',u'6',u'AD']

def atualizar(page,q=False,ad=None,ex=u'',imp=[]):
    if page.namespace() == 0: page = page.toggleTalkPage()
    elif page.namespace() != 1: return None
    if page.exists(): texto = page.get()
    else: texto = u''
    marca = bmarca.search(texto)
    if marca: marca = [p for p in marca.group(1).split('|')]
    marcas = [[m[1]]+[m[3]] for m in bmarcas.findall(texto)]
    if not marcas and not marca and not ad and not imp:
	if texto: pywikibot.output(u'Não foram encontradas marcas em '+page.title())
	else: pywikibot.output(page.title()+u' não existe...')
	return None
    elif not marcas and marca and q == -1 and (not [a for a in ad.split(u'|') if a not in marca] or [e for e in ex.split(u'|') if e in marca]):
	pywikibot.output(u'Não foram encontradas marcas para atualizar em '+page.title())
	return None
    if q: q = avaliar(page.toggleTalkPage())
    if marca: qualidade = marca[0]
    elif marcas:
	qmarcas = bqua.findall(str(marcas))
	if qmarcas: qualidade = qmarcas[0]
	else: qualidade = None
    else: qualidade = None
    if qualidade not in qs: qualidade = u'?'
    if q and q[0] > 4:
	qualidade = str(q[0])
	q = False
    nova = u'{{marca de projeto|%s' % qualidade
    rev = None
    if marca and len(marca) > 1:
	for i, p in enumerate(marca):
	    if p.startswith(u'rev='):
		rev = p
	    elif p.startswith(u'bot='):
		if q and not reav and p[6:] and date(int(p[6:10]),int(p[10:12]),int(p[12:14])).toordinal() + 182 > date.today().toordinal():
		    pywikibot.output(page.title()+u' foi avaliado por robô a menos de 6 meses, não foi reavaliado.')
		    return None
	marca = filter(lambda x:u'=' not in x,marca)
	if len(marca) % 2 == 0: marca.append(u'?')
	for p in marca[1:]: nova += u'|'+p
    if marcas:
	imarcas = [[m[0]]+bimp.findall(m[1]) for m in marcas]
	for m in imarcas:
	    if len(m) == 2: nova += u'|'+m[0]+u'|'+m[1]
	    else: nova += u'|'+m[0]+u'|?'
    if ad and [e for e in ex.split(u'|') if e in nova.split(u'|')]: ad = None
    elif ad:
	ad = [a for a in ad.split(u'|') if not u'|'+a.lower()+u'|' in nova.lower()]
	for m in ad: nova += u'|'+m+u'|?'
    if q: nova += u'|bot=%d/{{subst:CURRENTYEAR}}{{subst:CURRENTMONTH}}{{subst:CURRENTDAY2}}' % q[0]
    if not rev:
	rev = brev.search(str(marcas))
	if rev: rev = rev.group(0)
    if rev: nova += u'|'+rev+u'}}\n'
    else: nova += u'|{{subst:rev}}}}\n'
    impsum = {}
    if imp:
	for i in imp:
	    if i == 'eimp': continue
	    iindex = nova.lower().find(i.strip().lower()+u'|') + len(i) + 1
	    if iindex > 20 and nova[iindex] not in imp['eimp']:
		nova = nova[0:iindex] + imp[i].strip() + nova[iindex+1:]
		impsum[i] = imp[i]
    if marcas: texto = bmarcas.sub('',texto)
    if marca: texto = bmarca.sub('',texto)
    if texto.count(u'{{',0,texto.find(u'\n==')) < 3: texto = re.sub(ur'{{[Aa]vançarDiscussão}}\n?',u'',texto)
    texto = re.sub(ur'^({{[Aa]vançarDiscussão}} ?\n?|.*?)',r'\1'+nova,texto)
    if type(q) == tuple:
	if ad: sumario = u'Bot: adicioando marca "%s" e avaliando [[Wikipédia:Qualidade|qualidade]]: %d (%s)' % (ad[0],q[0],q[1])
	else: sumario =  u'Bot: avaliando [[Wikipédia:Qualidade|qualidade]]: %d (%s)' % (q[0],q[1])
    elif ad:
	if marcas: sumario =  u'Bot: adicionando marca "%s" e atualizando marca(s) de wikiprojeto(s)' % ad[0]
	else: sumario =  u'Bot: adicionando marca "%s"' % ad[0]
    elif imp: sumario =  u'Bot: colocando importância em marca(s) de wikiprojeto(s)'
    else: sumario =  u'Bot: atualizando marca(s) de wikiprojeto(s)'
    if impsum:
	for i in impsum: sumario += u', importância %s para %s' % (impsum[i],i)
    if simular:
	if page.exists(): pywikibot.showDiff(page.get(),texto)
	else: pywikibot.output(u'Nova página:\n'+texto)
    else:
        try: page.put(texto,comment=sumario)
        except pywikibot.LockedPage:
            pywikibot.output(u'\03{lightred}' + page.title() + u'está protegida!\03{default}')
            return
    return (nova,sumario)

simular, reav = False, False

def main(*args):
    site = pywikibot.getSite()
    av, predef, cat, subcat, ad, atu , ex, imp, eimp= False, None, None, None, None, None, u'', [], []
    genFactory = pagegenerators.GeneratorFactory()
    for arg in pywikibot.handleArgs(*args):
	if arg.startswith(u'-predef'):
	    predef = arg[8:]
	    if not predef: predef = pywikibot.input(u'Qual predefinição?')
	    if predef:
		if predef.find(u':') != -1: predef = pywikibot.Page(site,predef)
		else: predef = pywikibot.Page(site,u'Predefinição:'+predef)
	elif arg == u'-avaliar':
	    av = True
	elif arg.startswith(u'-adicionar:'):
	    ad = arg[11:]
	elif arg.startswith(u'-avaliar:'):
	    qualidade = avaliar(pywikibot.Page(site,arg[9:]))
	    pywikibot.output(u'qualidade %d (%s)' % (qualidade[0],qualidade[1]))
	    return
	elif arg.startswith(u'-exceção:'):
	    ex = arg[9:]
	elif arg.startswith(u'-imp:'):
	    imp = dict([i.split(u':') for i in arg[5:].split(u';')])
	elif arg.startswith(u'-eimp:'):
	    eimp = arg[6:].split(u',')
	elif arg == u'-simular':
	    global simular
	    simular = True
	elif arg == u'-forçar':
	    global reav
	    reav = True
	elif arg == u'-comandos':
	    pywikibot.output(pagegenerators.parameterHelp)
	    return
	elif not genFactory.handleArg(arg):
	    pywikibot.output(u'#Comando não encontrado: '+ arg)
	    return
    if imp: imp['eimp'] = eimp
    for page in pagegenerators.PreloadingGenerator(genFactory.getCombinedGenerator()):
	if not page.namespace() in [0,1]: continue
	novo = atualizar(page,av,ad,ex,imp)
	t = page.title()
	t = t[0:t.find(u':')+1]+u'\03{lightblue}'+t[t.find(u':')+1:]+u'\03{default}' # Cor
	if novo: pywikibot.output(t+u' -> '+novo[1])


if __name__ == "__main__":
    try: main()
    finally: pywikibot.stopme()